package com.grass.cropTradingCenter.handler;

import com.grass.cropTradingCenter.common.BusinessException;
import com.grass.cropTradingCenter.common.OutputException;
import jodd.time.TimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.util.concurrent.TimeUnit;


@Slf4j
@Component
public class RepeatInterceptor extends InterceptorRegistry implements HandlerInterceptor {

    @Value("${grass.repeatClick}")
    Long repeatClick;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    RedissonClient redissonClient;

    private static final String REDIS_REPEAT_KEY = "REPEAT_KEY#";

    private static final String REDIS_LOCK = "REPEAT_LOCK#";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 如果不是映射到方法，可以直接访问
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        String remoteHost = request.getRemoteHost();
        int remotePort = request.getRemotePort();
        StringBuffer requestURL = request.getRequestURL();

        String repeatKey = REDIS_REPEAT_KEY + requestURL + "#" + remoteHost + "#" + remotePort;
        String repeatLock = REDIS_LOCK + repeatKey;


        RLock lock = redissonClient.getLock(repeatLock);
        boolean isLock = false;
        try {
            isLock = lock.tryLock(3, TimeUnit.SECONDS);
            if(isLock){
                if (Boolean.TRUE.equals(redisTemplate.hasKey(repeatKey))) {
                    throw new OutputException("重复点击");
                }
                redisTemplate.opsForValue().set(repeatKey, "1", Duration.ofMillis(repeatClick));
            }
        } catch (Exception e) {
            throw e;
        } finally {
            if (isLock)
                lock.unlock();
        }

        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
